package org.lex.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.Adler32;
import java.util.zip.CRC32;
import java.util.zip.Checksum;

import org.lex.io.IO;


/**
 * �ṩ����ķ��������ļ����ֽ�����CRC32��Adler32У��
 * 
 * @author Daniel Liu
 */
public class Checksums {
	private static final int DEFAULT_BUF_SIZE = 512;

	/************************
	 * Adler32
	 ******************/
	public static long adler32(File file) throws FileNotFoundException, IOException {
		return checksum(new Adler32(), file, DEFAULT_BUF_SIZE);
	}

	public static long adler32(File file, int bufsize) throws FileNotFoundException, IOException {
		return checksum(new Adler32(), file, bufsize);
	}

	/***************
	 * CRC32
	 ***************************/
	public static long crc32(File file) throws FileNotFoundException, IOException {
		return crc32(file, DEFAULT_BUF_SIZE);
	}

	public static long crc32(File file, int bufsize) throws FileNotFoundException, IOException {
		return checksum(new CRC32(), file, bufsize);
	}

	/******************************
	 * General checksum
	 **************************************/
	public static long checksum(Checksum checksum, File file, int bufsize) throws FileNotFoundException, IOException {
		FileInputStream in = new FileInputStream(file);
		long value = checksum(checksum, in, bufsize);
		IO.closeQuietly(in);
		return value;
	}

	public static long checksum(Checksum checksum, InputStream in, int bufsize) throws IOException {
		if (bufsize < 1)
			bufsize = DEFAULT_BUF_SIZE;
		byte[] buf = new byte[bufsize];
		int len = 0;
		while (true) {
			len = in.read(buf);
			if (-1 == len)
				break;
			else
				checksum.update(buf, 0, len);
		}
		return checksum.getValue();
	}

	public static long checksum(Checksum checksum, byte[] data) {
		return checksum(checksum, data, 0, data.length);
	}

	/**
	 * @param checksum
	 *            �����߸���ά����ĳ�ʼ״̬(�������ǰ��ִ��reset())
	 * @param data
	 * @param offset
	 * @param length
	 * @return
	 */
	public static long checksum(Checksum checksum, byte[] data, int offset, int length) {
		checksum.update(data, offset, length);
		return checksum.getValue();
	}

	private Checksums() {
	}
}
